"""
@-*- coding: utf-8 -*-
@ python：python 3.8
@ 创建人员:ylx-lingxiao
@ 创建时间:2024/10/23  23:13
@ File:study5.py
@ Explanation:函数
"""
"""
自定义函数

def add():
    print('大家好，我是曼巴')
    
    
    
函数写了放在那里，直接执行是不会有结果的，函数写了就需要调用，调用才会执行函数里的东西

调用如下

add()  打印 大家好，我是曼巴


传参形如：
def add(x,y):
    print(x+y)
    
    
add(3,2)   打印 5
b = add(3,2)
print(b)   打印None

此时我们的函数是没有返回值的所以不能赋值，我们要想有返回值，那么就要  return x+y
此时再输出b 就有值了，因为有返回值，再形如可以返回x,y,x+y   b输出一个元组(3,2,5)
同时返回多个值如return x+y,x-y,x,y,x/y   这个返回的结果是一个元组


a = [1,2,3,1,2,3,1,3,14]
删除列表里边所有1

def rm_list(a,b):
    num = a.count(b)
    for n in range(num):
        a.remove(b)
    print(a)
    return a
    
bb = rm_list(a,1)
print(bb)


question：
把值相同的列表分别赋值给a c 但是a c id不一样
对于可变对象，值一样，但是id有可能是不一样的，因为值可以修改而id不变，所以对列表来说，不看值一样，在这个列表出生的开始，它的id就定了，就是唯一的
所以尽管列表的值一样，但是id不一样，正是因为列表可以增删改，而id不变  对列表来说a = [1,2,3]  b = [1,2,3] 虽然值一样，但是id不同，因为对
a的修改，不会影响b----字典集合也是一样
如果列表的id一样 值一样，a变了c也要变，修改一个相当于2个都变了，因为引用的是同一个对象,这样写
a = b = [1]
print(id(a),id(b))




1.冒泡
首先return 的位置一定要对，所有循环走完再return 否则，比如说2个for循环嵌套，如果里边的有return，那么外面的for循环仅执行一次，因为见return就返回
整个循环结束,return不仅会终止内层循环还会终止整个函数的执行

pop删除在列表和字典的效果一致，按下标或者按key删除后，会有返回值
del删除在列表和字典也一样，就是一个删除的操作，没有返回值，del a[3]


a=[9,5,6,8,2,7,3,4,1]
解题思路--
第一轮，开始比8次
第一次 0 1
第二次 1 2
第三次 2 3

第8次 7 8 
第二轮比7次
依次类推



第一种--每次都是从头开始比较 每轮比8次，一共比8轮
for m in range(8):
    for n in range(8):
        if a[n] > a[n+1]:
            a[n],a[n+1] = a[n+1],a[n]
            

第二种虽然比8轮，但是每轮比完倒数已经从小到大排序，所以比的轮次是1-8，每轮比的次数是8-1
for m in range(8):
    print(f'-----{m}----')
    for n in range(8-m):
        if a[n] > a[n+1]:
            a[n],a[n+1] = a[n+1],a[n]
        print(a)
        
        
        
for m in range(len(a)-1):
    for n in range(len(a)-1-m):
        if a[n] > a[n+1]:
            a[n],a[n+1] = a[n+1],a[n]

print(a)

接下来我们将这个for循环封装成一个函数
def mao_pao(a):
    for m in range(len(a)-1):
        for n in range(len(a)-1-m):
            if a[n] > a[n+1]:
                a[n],a[n+1] = a[n+1],a[n]
    return a
    
    
调用：
a=[9,5,6,8,2,7,3,4,1]
aa = mao_pao(a)
print(aa)










函数：
所谓函数，就是把具有独立功能的代码块组织为一个小模块，在需要的时候调用函数的使用包含2个步骤
定义函数--封装独立功能
调用函数--享受封装的成果

函数的调用，不同的需求，参数可有可无
定义好函数后只是表示这个函数封装了一段代码而已
如果不主动调用函数，函数是不会执行的

如
def add():
    result = 1+ 2
    print(result)



add()

优化，支持输入数字求和
def add(m,n):
    result = m+n
    print(result)



add(110,120)


函数返回值的作用
在函数中，如果需要返回结果给用户需要使用函数返回值
使用return 关键字

def sum(a,b):
    return a+b
sum1 = sum(110,120)
print(sum1)



变量的作用域
变量的作用域主要指变量的生效范围，主要分为2类全局变量和局部变量，局部变量就是定义在函数体内部的变量，只能在函数体内部生效，临时保存数据，函数调用完成后销毁局部变量

全局变量就是在函数体内及外部都能生效的变量
a = 100

def test1():
    print(a)
    
def test2():
    print(a)
    
    
test1()   打印100
test2()   打印100


里边的临时结果你想用，那就return出来赋值给变量成为全局变量，那么既可全局都正常使用‘


在函数内部修改成为全局变量，使用global 关键字
a = 100

def test1():
    print(a)
    
def test2():
    global a
    a = 200
    print(a)
    
    
test1()   打印100
test2()   打印200
print(f'全局变量a是{a}') 打印200


以上2种方式可以将你的临时变量留下来  return返回重新赋值    使用global关键字

函数不能重名，如果重名将以最靠近下方的为主





理解类和对象    类是统称，对象是具象化的类，比如说 猫科动物   猫咪，猫科动物有共性的地方也有个性的地方
类是一系列具有相同特征和行为的事物的统称，是一个抽象的概念，不是真实存在的事物
特征是属性   属性对应的就是变量 值
行为是方法   行为就是函数，类里的函数叫方法

如果你要制造洗衣机，那么类就是制造洗衣机的图纸，而我们制造出来的洗衣机就是对象，所以类是用来创建对象的
对象是类创建出来的真实存在的事物，比如上面我们说的洗衣机
在开发中，先有类，再有对象


定义类
class 类名():    类名字母数字下划线，不能以数字开头
    代码


举例
class washer():
    def wash(self):
        print('我会洗衣服')
        
    def fix(self):
        print('我会修洗衣机')
        

创建对象，对象又名实例，我们创建对象的过程又叫实例化对象
对象名 = 类名()
创建对象   haier1 = washer()
haier1对象调用实例方法
haier1.wash()        打印 我会洗衣服
haier1.fix() 打印 我会修洗衣机

我们还可以实例化下一个对象
haier2 = washer()
haier2对象调用实例方法
haier2.wash()        打印 我会洗衣服
haier2.fix() 打印 我会修洗衣机

实例化这个类，我就拥有了这个类下的所有方法


类就好比一个图纸，只要你实例化它成为对象，那么谁都可以按照图纸，拥有类中所有的方法


但是类中的函数又比我们之前单独的函数多了个self，且我再调用这个方法时，我还不用传递参数
这个self就是对象本身，它把自己传递进去了
class washer():
    def wash(self):
        print('我会洗衣服')
        self.fix()
        
    def fix(self):
        print('我会修洗衣机')
        
hello = washer()
hello.wash()    
打印：
我会洗衣服
我会修洗衣机



实例化对象我们是可以给它添加属性的，属性就是特征，比如洗衣机的高度，宽度，重量
对象属性可以在类外添加获取，也可以在类里面添加和获取
类外添加对象属性
对象名.属性名 = 值
haier1.width = 500
haier1.height = 800

类外获取对象属性
对象名.属性名
print(f'haier1洗衣机的高度为{haier1.height}')


类里获取对象的属性
self.属性名


class washer():
    def wash(self):
        print('我会洗衣服')
        
    def fix(self):
        if self.height >= 400:
            print('我修不了，我只会修高小于300的洗衣机洗衣机')
        else:
            print(f'我可以修这个型号的，高为{self.height}的洗衣机')
        
hello = washer()
hello.width = 500
hello.height = 300
print('洗衣机宽为{hello.width}')---------类外调用
hello.fix()    打印   我可以修这个型号的，高为300的洗衣机

类里的self就是你实例化的对象，类中self的作用就是将你的实例化对象传入进去，因为你也不知道后面实例化对象的名称，所以我们统一叫self
类里的函数的入参，第一个要留给对象

上述我们采用的是类外添加属性，但是如果我们类外忘记添加属性了，那你后续的执行就会报错
第一个错就会出现再print('洗衣机宽为{hello.width}')，因为width的属性没有给，所以这个print打印不出来，那注释掉这个print后
实例化的hello对象使用fix方法时，也会报错，因为类里的self.height无值，没有办法比较大小，报错是washer这个类没有height这个属性

为了解决上述问题，我们需要一个魔法方法，在Python中__xx__()的函数囧啊魔法方法，指的是具有特殊功能的函数
我们本次使用__init__()
洗衣机的宽高是与生俱来的属性，我们是否可以在初始的过程中就赋予这个属性呢？
==__init__()方法的作用：初始化对象，==，也就是说这个对象在实例化类的时候，我给你加一些默认的属性，比如说你想构建一个洗衣机
那你必须要告诉我这个洗衣机的长宽高，你如果不告诉我，那我就不让你实例化这个对象

第一种写死
class washer():
    def __init__(self):
        self.width = 500
        self.height = 300
    def wash(self):
        print('我会洗衣服')
        
    def fix(self):
        if self.height >= 400:
            print('我修不了，我只会修高小于300的洗衣机洗衣机')
        else:
            print(f'我可以修这个型号的，高为{self.height}的洗衣机')



这个def __init__ 方法在你实例化这个类的时候就已经执行了,这样在你实例化这个类时，对象就有了默认的属性，那后续方法使用这个属性，就可以正常使用了

比如
manba = washer()
print(f'{manba.height}')
print(f'{manba.width}')



第二种，灵活的，值由实例化对象来指定
带参数的__int__()

class washer():
    def __init__(self,width,height):
        self.width = width    左边是将来类中的属性，右边相当于形参，这个值是要在你实例化这个类的时候传递进来的，我赋值给对象，作为其属性
        self.height = height
    def wash(self):
        print('我会洗衣服')
        
    def fix(self):
        if self.height >= 400:
            print('我修不了，我只会修高小于300的洗衣机洗衣机')
        else:
            print(f'我可以修这个型号的，高为{self.height}的洗衣机')


haier3 = washer(100,500)   你实例化这个对象时，你需要先掉__init__方法，其需要2个参数，传入后，给你这个对象，作为属性值


继承的概念，Python中类是可以继承的
Python面向对象的继承指的是类之间的所属关系，既子类默认继承父类所有的属性和方法

class master():
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
        
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
        
        
        
class tudi(master):
    pass
    
class tudi1(master):
    def make_new_cake(self):
        print('制作榴莲味的煎饼果子')
        
        
class grand_son(tudi1):
    def make_new_cake(self):
        print('制作黄瓜味的煎饼果子')         
        
daqiu = tudi()   创建对象
print(daqiu.kongfu) 对象访问实例属性
daqiu.make_cake() 对象调用实例方法
    

daqiu_1 = tudi1()
daqiu1.make_new_cake()


daqiu2 = grand_son()
daqiu2.   此时这个对象就会有爷爷辈  爸爸辈 和自己的方法及属性


类建议首字母大写，美观，易区分

问题解答：详情见723问题讨论
1.学习成绩大于等于90 用A表示，60-89用B表示，60以下用C表示
如果想实现一次判断多个，比如说用户是一组成绩，那么我们的方法就是split拆分为列表，for循环取列表的值来判断
有限个数，我们需要针对每个去给出结论，我们使用for即可


2.2个元素之间有对应关系的list，构造一个dict
这个中除了用for循环还可以用什么方法

比如说一些特殊类型的列表可以直接转化为字典,列表中的元祖长度为2时可以转化，或者更普遍的来说，就是你的子元素的长度为2，能让我拆成key value的形式即可

list_1 = [(1,2),(3,4)]
print(dict(list_1))
输出 {1:2,3:4}

list_1 = ['12',(3,4)]
print(dict(list_1))
输出 {1:2,3:4}

再比如
list_2 = ([1,2],[3,4])
print(dict(list_2))
输出 {1:2,3:4}



正常转化如下
a = [1,2,3]
b = [4,5,6]
zip(a,b)
print(list(zip(a,b)))    本身的操作就是会将下标相同的2个元素，放在一个元组中  前a key   后b value   调换ab位置，则key value 顺序调整
打印[(1,4),(2,5),(3,6)]

所以我们使用
dict(zip(a,b))  来转化对应的下标成为列表，这个只找大家下标都有值的，匹配不上的，比如说某个超出了，匹配不上的就忽略


再形如zip的用法，可以将相同下标的放在一个元组内
a = [1,2,3]
b = [4,5,6]
c = [7,8]
print(list(zip(a,b,c)))
输出-[(1,4,7),(2,5,8)]
zip转换后，其本身类型就是zip,你可以使用其他基础数据类型做相关的转化，转字典比较特殊，要求元素长度必须为2才可以

for循环解决
a = [1,2,3]
b = [4,5,6]
c = {}
for n in range(len(a)):
    c[a[n]] = b[n]
    print(c)
print(c)

    

"""

"删除列表里边所有1"
# def rm_list(a,num):
#     nn = 0
#     for n in range(len(a)):
#         if a[n] == 1:
#             nn+=1
#         else:
#             pass
#
#     print(nn)
#
#     for m in range(nn):
#         a.remove(num)
#
#     print(a)
#
# aa = [1, 2, 3, 1, 2, 3, 1, 3, 14]
# rm_list(aa,1)

